package com.zjpavt.client.extenddevice;

import com.zjpavt.client.enums.ExtendDeviceEnum;
import com.zjpavt.client.event.EventRegisterCenter;
import com.zjpavt.client.extenddevice.gps.IGpsLigthSensationDevcie;
import com.zjpavt.client.extenddevice.lightsensation.ILightSensationDevice;
import com.zjpavt.client.hal.ExtendDeviceManager;
import com.zjpavt.client.nativemethod.JnIMethod;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * gps传感器获取gps信息类
 *
 * @author cjp
 */
@Slf4j
public class GpsLigthSensationSensor extends AbstractExtendDevice implements IGpsLigthSensationDevcie {
    private static final int MAX_LATITUDE = 90;
    private static final int MAX_LONGITUDE = 180;
    public static final DecimalFormat LONGITUDE_AND_LATITUDE_FORMATE = new DecimalFormat("#0.0000");
    private static final ScheduledThreadPoolExecutor gpsThreadPool = new ScheduledThreadPoolExecutor(1, new DefaultThreadFactory("gpsThreadPool"));
    private static final ScheduledThreadPoolExecutor gpsLightThreadPool = new ScheduledThreadPoolExecutor(1, new DefaultThreadFactory("gpsLightThreadPool"));

    /**
     * 光照度
     */
    private double lux;
    /**
     * 经度
     */
    private double longitude=120.142743;
    /**
     * 东经/西经
     */
    private char longitedeSymbol = 'E';
    /**
     * 纬度
     */
    private double latitude=30.319629;
    /**
     * 南纬/北纬
     */
    private char latitudeSymbol = 'N';
    /**
     * GPS是否有信号
     */
    private boolean GPSUseful = false;

    private int extendNum =0;

    public static final Pattern GPS_PATTERN = Pattern.compile("<LUX_GPS_DATA_(?<lux>[0-9.]{1,10})/\\$GNRMC," +
            "(?<time>[0-9.]{10}),(?<useful>[VA]),(?<latitude>[0-9.]{1,12}),(?<lat>[NS])" +
            ",(?<longitude>[0-9.]{1,12}),(?<lng>[EW])[^>]*>");

    public static final Pattern GPS1_PATTERN = Pattern.compile("<LUX_GPS_DATA_(?<lux>[0-9.]{1,10})/GPS_DATA_ERROR>");

    public static final Pattern GPS = Pattern.compile("<GPS_DATA_\\$GNRMC,(?<time>[0-9.]{9,10}),(?<useful>[VA]),"
                                      + "(?<latitude>[0-9.]{1,12}),(?<lat>[NS]),(?<longitude>[0-9.]{1,12}),(?<lng>[EW])[^>]*>");

    public GpsLigthSensationSensor(int extendNum,ExtendDeviceEnum deviceType) {
        super(extendNum,ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(extendNum).getDeviceType());
        this.extendNum = extendNum;
        if(ExtendDeviceEnum.GPS.equals(deviceType)) {
            gpsInformationTask();
        } else if(ExtendDeviceEnum.LIGHT.equals(deviceType)) {
            updateInformationTask();
        }
    }

    private void gpsInformationTask() {
        updateGpsInformation();
        gpsThreadPool.schedule(()-> {
//			如果检查周期小于30S 则不继续更新等待下次
            if (System.currentTimeMillis() - getLastQueryTime() < 30 * 1000) {
            } else {
                updateGpsInformation();
            }
        },60, TimeUnit.SECONDS);
    }

    public GpsLigthSensationSensor updateGpsInformation() {
        ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(this.extendNum).setDeviceType(ExtendDeviceEnum.GPS);
        String gpsInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(), "<AT_CHECK0_GPS_DATA>", 200);
        if (gpsInformation == null) {
            getUnderDeviceInteractionBean().interactionFail();
            return this;
        } else {
            getUnderDeviceInteractionBean().interactionSuccess();
        }
        Matcher matcher = GPS.matcher(gpsInformation);
        if (matcher.matches()) {
            setLastQueryTime();
            String useful = matcher.group("useful");
            if ("A".equals(useful)) {
                this.latitude = Double.parseDouble(matcher.group("latitude")) / 100;
                this.longitude = Double.parseDouble(matcher.group("longitude")) / 100;
                this.latitudeSymbol = matcher.group("lat").charAt(0);
                this.longitedeSymbol = matcher.group("lng").charAt(0);
                this.GPSUseful = true;
                matcher.group("time");
            } else {
                this.GPSUseful = false;
            }
        } else {
            this.GPSUseful = false;
        }
        return this;
    }

    private void updateInformationTask() {
        updateGpsLigthInformation();
        gpsLightThreadPool.schedule(()-> {
//			如果检查周期小于30S 则不继续更新等待下次
            if (System.currentTimeMillis() - getLastQueryTime() < 30 * 1000) {
            } else {
                updateInformationTask();
            }
        },60, TimeUnit.SECONDS);
    }

    /**
     * 更新设备信息 获取最新的数据
     */
    public GpsLigthSensationSensor updateGpsLigthInformation() {
//		如果查询时间小于10秒 则不更新数据
        String gpsInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(), "<AT_CHECK0_LUX_GPS_DATA>", 200);
        if (gpsInformation == null) {
            getUnderDeviceInteractionBean().interactionFail();
            return this;
        } else {
            getUnderDeviceInteractionBean().interactionSuccess();
        }
        Matcher matcher1 = GPS1_PATTERN.matcher(gpsInformation);
        if (matcher1.matches()) {
            this.GPSUseful = false;
            this.lux = Double.parseDouble(matcher1.group("lux"));
            if(this.lux <99999 && this.lux >=0) {
                ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(this.extendNum).setDeviceType(ExtendDeviceEnum.LIGHT);
                IExtendDevice ie = ExtendDeviceManager.getInstance().getExtendDevice(ExtendDeviceEnum.LIGHT);
            }
            return this;
        }
        Matcher matcher = GPS_PATTERN.matcher(gpsInformation);
        if (matcher.matches()) {
//			刷新更新时间
            setLastQueryTime();
            String useful = matcher.group("useful");
            if ("A".equals(useful)) {
                this.latitude = Double.parseDouble(matcher.group("latitude")) / 100;
                this.longitude = Double.parseDouble(matcher.group("longitude")) / 100;
                this.latitudeSymbol = matcher.group("lat").charAt(0);
                this.longitedeSymbol = matcher.group("lng").charAt(0);
                this.GPSUseful = true;
                matcher.group("time");
            } else {
                this.GPSUseful = false;
            }
            this.lux = Double.parseDouble(matcher.group("lux"));
        } else {
            this.lux = -1;
            this.GPSUseful = false;
        }
        if(this.GPSUseful ==true && (this.lux >99999 || this.lux <0)) {
            ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(this.extendNum).setDeviceType(ExtendDeviceEnum.GPS);

            IExtendDevice ie = ExtendDeviceManager.getInstance().getExtendDevice(ExtendDeviceEnum.GPS);

        } else if(this.GPSUseful ==false && this.lux <99999) {
            ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(this.extendNum).setDeviceType(ExtendDeviceEnum.LIGHT);
            IExtendDevice ie = ExtendDeviceManager.getInstance().getExtendDevice(ExtendDeviceEnum.LIGHT);
        } else if(this.GPSUseful ==true && this.lux <99999 && this.lux >=0) {
            ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(this.extendNum).setDeviceType(ExtendDeviceEnum.GPS_LIGHT);
            IExtendDevice ie = ExtendDeviceManager.getInstance().getExtendDevice(ExtendDeviceEnum.GPS_LIGHT);
        } else {
            ExtendDeviceManager.getInstance().getExtendDeviceByExtendNum(this.extendNum).setDeviceType(ExtendDeviceEnum.GPS);
        }
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.GPS.getDeviceName());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DATA_EXCHANGE, dataMap);
        return this;
    }

    public static final DecimalFormat LAT_AND_LNG_FORMAT = new DecimalFormat("#0.000000");
    /**
     * @return 获取格式化后的位置  如12.266E_125.36N
     */
    @Override
    public String returnForFCommand() {
        if (!isGPSUseful()) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(LAT_AND_LNG_FORMAT.format(this.longitude))
        .append(longitedeSymbol == 0?"E":longitedeSymbol)
        .append("_")
        .append(LAT_AND_LNG_FORMAT.format(this.latitude))
        .append(latitudeSymbol == 0?"N":latitudeSymbol);
        return  stringBuilder.toString();
    }
    /**
     * 资源互斥通过拓展通道自带的锁实现
     * 尝试通过485获取GPS信号
     * @return
     */
    private static double[] getGpsInfomation() {
        return new double[1];
    }

    @Override
    public boolean isGPSUseful() {
        return GPSUseful;
    }

    @Override
    public double getLux() {
        return lux;
    }

    public static final DecimalFormat LUX_FORMAT = new DecimalFormat("00000");

    /**
     * 返回给P指令使用
     * @return
     */
    @Override
    public String returnForPCommand() {
        return LUX_FORMAT.format(lux);
    }

    @Override
    public ILightSensationDevice updateLightSensationInformation() {
        return updateGpsLigthInformation();
    }
}
